home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / Rewrite 0.2.6 / ReWrite 0.2.6 Docs / ReWrite 0.2.6 Docs.rsrc / TEXT_130.txt < prev    next >
Encoding:
Text File  |  1995-08-23  |  5.4 KB  |  117 lines

  1.  
  2. Chapter 2 - Simple Examples
  3.  
  4. This section contains some simple examples of programs written in the language to give an idea of what it looks like.
  5.  
  6. Factorial
  7.  
  8. This example calculates the factorial of an argument. 
  9.  
  10.   factorial[0] -> 1;
  11.   factorial[n] -> n * factorial[n-1];
  12.  
  13.   top[] -> outnum[factorial[6]];
  14.  
  15.    A ReWrite program consists of a list of rewrite rules separated by semi-colons;
  16. each rule defines a transformation and is part of a function. The basic structure is
  17.   rule [patterns ]  -> rhs ;
  18. A match needs to be made with the patterns in order for a particular rule to be used. The rule used will be the first one that matches.
  19.  
  20.    For example, with the function factorial defined above, if it is called:
  21. -  with more than two arguments or no argument it will fail;
  22. -  with the integer 0 the first rule will be activated and 1 will be returned;
  23. -  with any value n other than 0 the second rule will be activated, and
  24.                n * factorial[n-1]
  25.     will be calculated, calling factorial again. (If n<0, this will be a problem)
  26.  
  27.    A program must somewhere contain a rule top[] -> ...
  28.  When a program is executed, it needs to have a well defined starting point, so the function top[] is called, and whatever rule that matches is activated.
  29.  
  30.    The above function will fail to terminate if the argument is not an integer or is negative. This problem could be prevented using the following modified function:
  31.  
  32.   factorial[0] -> 1;
  33.   factorial[n:int]::n>0 -> n * factorial[n-1];
  34.  
  35.    This introduces another idea used in ReWrite; conditions (sometimes called guards in functional programming languages). There are two sorts used here:
  36.  
  37. ‚Ä¢   parameter :type 
  38.  
  39.    This is used to indicate that a parameter to a function must be a certain type or the rule won't match.
  40.  
  41. ‚Ä¢   rule [patterns ]::condition  -> rhs ;
  42.  
  43.    In this case the patterns  must match and the condition  must be satisfied, otherwise the rule won't match.
  44.  
  45. Equals
  46.  
  47.   equal[x,x] -> true;
  48.   equal[x,y] -> false;
  49.  
  50.    This function will return true if called with any two arguments that are the same, as the match with the first rule will only succeed if it is given two equal arguments, since both of the arguments have the same name. (the x appearing twice makes it a non-linear rule). false will be returned if the two arguments are different.
  51.    Non-linear rules are a very powerful part of the pattern matching.
  52.  
  53. Insert into ordered list
  54.  
  55. This function inserts a value (a number) into its correct place of a list of ascending order.
  56.  
  57.   insert[x,{}] -> x;
  58.   insert[x,{a,.rest}]::x<a -> {x,a,.rest};
  59.   insert[x,{a,.rest}] -> {a,.insert[x,rest]};
  60.  
  61.    A list (represented {...}) is a way of gathering a collection of values into a single value. A splice (represented by a preceding .) is the reverse of a list; it takes a list and turns it into its components.
  62.  
  63.    In the example above,
  64.   insert[x,{a,.rest}]
  65. will be matched if the first argument is any value and the second argument is a list containing at least one element. The first element of the list will be called a; the rest will be gathered into another list called rest. From this example it can be seen that list and splice act in the 'opposite' way when used as part of a match on the left hand side.
  66.  
  67.    For example if
  68.   insert[3,{1,4,5}] was called then
  69.       x would have the value 3,
  70.       a would have the value 1,
  71.       rest would have the value {4,5} for the duration of that rule.
  72.  
  73.    Continuing that example, x is not less than a, so the second rule is not matched, but the third one is so the next step will be:
  74.      {1,.insert[3,{4,5}]}                                                                 (*)  
  75. When insert[3,{4,5}] is called,
  76.       x will be 3,
  77.       a will be 4,
  78.       rest will be {5},
  79. so the second rule is matched and the right hand side of this will be:
  80.      {3,4,.{5}}
  81. which becomes
  82.      {3,4,5} (remember splice undoes a list)
  83. which going back into (*) gives:
  84.      {1,3,4,5}
  85. The expected result.
  86.  
  87.    Another (higher level) way of expressing the function is this:
  88.  
  89.   insert[x,{.lt,a,b,.gt}]::a<=x & x<b -> {.lt,a,x,b,.gt};
  90.   insert[x,{a,.gt}]::x<a -> {x,a,.gt};
  91.   insert[x,l:lis] -> {.lis,x};
  92.  
  93.    This example shows the splice operator used in a way that requires backtracking - there is more than one match that may work, so all the possible matches are checked in a systematic way until a match is found that works, or the match fails.
  94.  
  95.    The first rule is the usual case, where the two elements to insert x between are found, so the match breaks up the list into a part consisting of elements less than or equal to x (.lt,a) and a part consisting of elements greater than x (b,.gt),
  96.   The second rule deals with the case where x is smaller than all of the elements on the list,
  97.    The third rule deals with either the case where the list is empty or x is larger than all of the elements in the list (as if the first two rules are not matched, these are the only cases left).
  98.  
  99.    This list/splice notation is very powerful and can mean easy definition of what would otherwise be low level functions.
  100.    For example (for those of you that know lisp):
  101.  
  102.   car[{x,.rest}] -> x;
  103.  
  104.   cdr[{x,.rest}] -> rest;
  105.  
  106.   cons[x,rest] -> {x,.rest};
  107.  
  108.   join[x:lis,y:lis] -> {.x,.y};
  109.  
  110. Bubblesort
  111.  
  112.    This is a very simple sort algorithm on a list - it simply takes any two elements that are in the wrong order and swaps them, repeating until done. Although simply expressed, it is not very efficient - the worst case is O(N^3).
  113.  
  114.   sort[{.a,b,c,.d}]::b>c -> sort[{.a,c,b,.d}];
  115.   sort[x:lis] -> x;
  116.  
  117.